<template>
  <div class="containers" ref="content">
    <div class="canvas" ref="canvas"></div>
    <div id="js-properties-panel" class="panel"></div>
    <ul class="buttons">
      <li>下载</li>
      <li>
        <a ref="saveDiagram" href="javascript:;" title="download BPMN diagram">BPMN diagram</a>
      </li>
      <li>
        <a ref="saveSvg" href="javascript:;" title="download as SVG image">SVG image</a>
      </li>
       <li>
        <Button type="primary" @click="save" :disabled="!xmlStr">保存</Button>
      </li>
    </ul>
  </div>
</template>

<script>
  // 引入API接口
  // import {getBpmnXml, saveBpmnData, getNodeData} from '../../api/modeler'
   // 引入相关的依赖
  import BpmnViewer from 'bpmn-js'
  import BpmnModeler from 'bpmn-js/lib/Modeler'
  import propertiesPanelModule from 'bpmn-js-properties-panel'
  import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
  import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'
  import Modeling from 'bpmn-js/lib/features/modeling/Modeling'
  // 语言包
  import customTranslate from '../assets/customTranslate/customTranslate';

  // 引入tab的配置文件
import magicPropertiesProviderModule from '../assets/provider/magic';
import magicModdleDescriptor from '../assets/descriptors/magic';

  export default {
    data(){
      return {
        id: "",
        bpmnModeler: null,
        container: null,
        canvas: null,
        xmlStr: null,
        // 点击节点获取的数据
        nodeCode: "",
        nodeName: ""
      }
    },
    methods:{
      createNewDiagram() {
        const that = this;
        let params = {
          id: this.id
        };
        // 与后台交互获取到bpmnXmlStr
//         getBpmnXml(params).then(res => {
//           const bpmnXmlStr = res.obj;
// //          console.log(bpmnXmlStr)
//           this.bpmnModeler.importXML(bpmnXmlStr, function (err) {
//             if (err) {
//               console.error(err);
//             }
//             else {
//               // 字符串转换成图成功后执行的函数
//               that.success()
//             }
//             // 让图能自适应屏幕
//             var canvas = that.bpmnModeler.get('canvas');
//             canvas.zoom('fit-viewport');
//           });
//         })

          // 获取到建模图形
          const bpmnXmlStr = JSON.parse(localStorage.getItem('bpmnModel')).bpmnXml;
          this.bpmnModeler.importXML(bpmnXmlStr, (err) => {
            if (err) {
              console.error(err);
            }
            else {
              // 字符串转换成图成功后执行的函数(获取到图形之后的函数)
              this.success()
            }
            // 让图能自适应屏幕
            this.bpmnModeler.get('canvas').zoom('fit-viewport');
          });
      },

     // 增加事件监听器在Modeling里 
      success() {
        const bpmnjs = this.bpmnModeler;
        const eventBus = bpmnjs.get('eventBus');
        const elementFactory = bpmnjs.get('elementFactory');
//        viewer没有这两个 所以不传了，
//        如果是Modeler,应该要引入且const modeling = new Modeling(eventBus,elementFactory,commandStack,bpmnRules);
//        const commandStack = bpmnjs.get('commandStack');
//        const bpmnRules = bpmnjs.get('bpmnRules');
        
        const modeling = new Modeling(eventBus,elementFactory);
        this.addBpmnListener(this, modeling);
      },
      addBpmnListener(_self,modeling) {
        const bpmnjs = this.bpmnModeler;
        const eventBus = bpmnjs.get('eventBus');
        // 监听模型的事件
        const events = [
          'element.click',
          'element.dblclick'
        ];
        events.forEach(function(event) {
          eventBus.on(event, function(e) {
            // console.log(event + '   ' + JSON.stringify(e.element));
            if(e.element.type=='bpmn:Process'||e.element.type=='bpmn:Lane')
              return;

            var elementRegistry = bpmnjs.get('elementRegistry');
            var shape = elementRegistry.get(e.element.id);
            // 改变颜色
            // modeling.setColor(shape,{ stroke:'RED' });

            // console.log(shape)
            // 获取触发节点的id和name
            _self.nodeCode = shape.businessObject.id;
            _self.nodeName = shape.businessObject.name;    
           // console.log(_self.nodeCode)
           // console.log(_self.nodeName)        
        });
      })
    },
     // 保存修改操作
    save() {
      // 传给后台的参数
      let params = {
        id: this.id,
        bpmnXml: this.xmlStr
      };
      // 调用API接口
      // saveBpmnData(params).then(res => {
      //          console.log(res)
      //          console.log(this.xmlStr)
      //  })
      localStorage.setItem('bpmnModel', JSON.stringify(params));
    },
    // 下载为SVG格式,done是个函数，调用的时候传入的
    saveSVG(done) {
      // 把传入的done再传给bpmn原型的saveSVG函数调用
      this.bpmnModeler.saveSVG(done);
    },
    // 下载为SVG格式,done是个函数，调用的时候传入的
    saveDiagram(done) {
      // 把传入的done再传给bpmn原型的saveXML函数调用
      this.bpmnModeler.saveXML({ format: true }, function(err, xml) {
        done(err, xml);
      });
    },
    // 当图发生改变的时候会调用这个函数，这个data就是图的xml
    setEncoded(link, name, data) {
      // 把xml转换为URI，下载要用到的
      var encodedData = encodeURIComponent(data);
      // 获取到图的xml，保存就是把这个xml提交给后台
      this.xmlStr = data;
      // 下载图的具体操作,改变a的属性，className令a标签可点击，href令能下载，download是下载的文件的名字
      if (data) {
        link.className = "active";
        link.href = "data:application/bpmn20-xml;charset=UTF-8," + encodedData;
        link.download = name;
      } else {
        // xml不存在时
      }
    },
    // 更新建模图
    updateModel () {
      // 传给后台的参数
      let params = {
        id: this.id,
        bpmnXml: this.xmlStr
      };
      // 调用API接口
      // saveBpmnData(params).then(res => {
      //          console.log(res)
      //          console.log(this.xmlStr)
      //  })
      localStorage.setItem('bpmnModel', JSON.stringify(params));
    }
  },
  mounted(){
    this.container = this.$refs.content;
    const canvas = this.$refs.canvas;
    const customTranslateModule = {
      translate: [ 'value', customTranslate ]
    };
    this.bpmnModeler = new BpmnModeler({
      container: canvas,
      // 快捷键
      keyboard: {
        bindTo: window
      },
      //添加控制板
      propertiesPanel: {
        parent: "#js-properties-panel"
      },
      additionalModules: [
        // 左侧的工具栏集节点
        propertiesPanelModule,
        // 右侧的工具栏
        propertiesProviderModule,
        magicPropertiesProviderModule,
        customTranslateModule
      ],
      moddleExtensions: {
        camunda: camundaModdleDescriptor,
        magic: magicModdleDescriptor
      }
    });
 
    // 获取a标签dom节点
    var downloadLink = this.$refs.saveDiagram;
    var downloadSvgLink = this.$refs.saveSvg;
    let _this = this;
    // 给图绑定事件，当图有发生改变就会触发这个事件* **（绑定事件操作）
    this.bpmnModeler.on("commandStack.changed", function() {
        // 保存svg格式的图片供后面下载
        _this.saveSVG(function(err, svg) {
        _this.setEncoded(downloadSvgLink, "diagram.svg", err ? null : svg);
      });
      // 保存BPMN diagram格式的文件供后面下载
      _this.saveDiagram(function(err, xml) {
        _this.setEncoded(downloadLink, "diagram.bpmn", err ? null : xml);
      });
    });
    // this.id = this.bpmnId;
    //  不需要编辑功能，所以只用Viewer就够了，之前都是Modeler
    this.createNewDiagram(this.bpmnModeler);
  },
    // 父组件传来的id值 
    // props: [
    //   "bpmnId",
    //   "modelId"
    // ]
}
</script>

<style lang="scss">
/*左边工具栏以及编辑节点的样式*/
@import "bpmn-js/dist/assets/diagram-js.css";
@import "bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
@import "bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
@import "bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
/*右边工具栏样式*/
@import "bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css";
.containers {
  position: absolute;
  background-color: #ffffff;
  width: 100%;
  height: 90%;
}
.canvas {
  width: 100%;
  height: 100%;
}
.panel {
  position: absolute;
  right: 0;
  top: 0;
  width: 300px;
}
.buttons {
  position: absolute;
  left: 30px;
  bottom: 20px;
  & > li {
    display: inline-block;
    margin: 5px;
    & > a {
      color: #999;
      background: #eee;
      cursor: not-allowed;
      padding: 8px;
      border: 1px solid #ccc;
      &.active {
        color: #333;
        background: #fff;
        cursor: pointer;
      }
    }
  }
}
</style>